package com.zyw.boot.tool;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class DatabaseToEnumConverter {

    private static class ColumnInfo {
        Integer ordinalPosition;
        String columnName;
        String javaType;

        ColumnInfo(Integer ordinalPosition, String columnName, String javaType) {
            this.ordinalPosition = ordinalPosition;
            this.columnName = columnName;
            this.javaType = javaType;
        }

        Integer getOrdinalPosition() {
            return ordinalPosition;
        }

        String getColumnName() {
            return columnName;
        }

        String getJavaType() {
            return javaType;
        }
    }

    public static void main(String[] args) throws SQLException, IOException {
        String url = "jdbc:mysql://172.16.1.37:3306/singleEnum";
        String user = "root";
        String password = "password";
        String databaseName = "singleEnum";
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
        try (Connection connection = DriverManager.getConnection(url, user, password)) {
            DatabaseMetaData metaData = connection.getMetaData();

            // 获取所有表
            ResultSet tables = metaData.getTables(databaseName, null, "%", new String[]{"TABLE"});
            while (tables.next()) {
                String tableName = tables.getString("TABLE_NAME");
                processTable(connection, metaData, databaseName, tableName);
            }
        }
    }

    private static void processTable(Connection connection, DatabaseMetaData metaData, String dbName, String tableName)
            throws SQLException, IOException {
        // 获取列信息并按顺序排序
        List<ColumnInfo> columns = new ArrayList<>();
        ResultSet rsColumns = metaData.getColumns(dbName, null, tableName, null);
        while (rsColumns.next()) {
            Integer ordinal = rsColumns.getInt("ORDINAL_POSITION");
            String colName = rsColumns.getString("COLUMN_NAME");
            Integer jdbcType = rsColumns.getInt("DATA_TYPE");
            String javaType = resolveJavaType(jdbcType);
            columns.add(new ColumnInfo(ordinal, colName, javaType));
        }
        rsColumns.close();

        if (columns.size() < 2) {
            System.out.println("表 " + tableName + " 列数不足2，跳过");
            return;
        }

        // 生成枚举类名
        String className = convertToPascalCase(tableName);
        StringBuilder code = new StringBuilder();

        // 生成枚举实例
        List<String> enumEntries = new ArrayList<>();
        try (Statement stmt = connection.createStatement();
             ResultSet rs = stmt.executeQuery("SELECT * FROM " + tableName)) {

            while (rs.next()) {
                // 处理枚举名称
                Object enumNameValue = rs.getObject(columns.get(1).getColumnName());
                String enumName = sanitizeEnumName(enumNameValue.toString());

                // 生成参数列表
                List<String> params = new ArrayList<>();
                for (ColumnInfo col : columns) {
                    Object value = rs.getObject(col.getColumnName());
                    params.add(toJavaLiteral(value, col.getJavaType()));
                }

                enumEntries.add(enumName + "(" + String.join(", ", params) + ")");
            }
        }
        ColumnInfo firstColumn = columns.get(0);
        String idColumnName = firstColumn.getColumnName();
        String idJavaType = firstColumn.getJavaType();
        String idGetterName = "get" + capitalize(idColumnName);

        // 生成枚举代码
        code.append("package enums;\n" +
                        "import java.util.HashMap;\n" +
                "import java.util.Map;\n\n").
                append("public enum ").append(className).append(" {\n    ")
                .append(String.join(",\n    ", enumEntries)).append(";\n\n");


        // 生成静态ID映射
        code.append("    private static final Map<").append(idJavaType).append(", ")
                .append(className).append("> ID_MAP = new HashMap<>();\n\n")
                .append("    static {\n")
                .append("        for (").append(className).append(" value : values()) {\n")
                .append("            ID_MAP.put(value.").append(idGetterName).append("(), value);\n")
                .append("        }\n")
                .append("    }\n\n");

        // 生成字段
        for (ColumnInfo col : columns) {
            code.append("    private final ").append(col.getJavaType()).append(" ")
                    .append(col.getColumnName()).append(";\n");
        }

        // 生成构造函数
        code.append("\n    ").append(className).append("(");
        List<String> params = new ArrayList<>();
        for (ColumnInfo col : columns) {
            params.add(col.getJavaType() + " " + col.getColumnName());
        }
        code.append(String.join(", ", params)).append(") {\n");
        for (ColumnInfo col : columns) {
            code.append("        this.").append(col.getColumnName()).append(" = ")
                    .append(col.getColumnName()).append(";\n");
        }
        code.append("    }\n\n");

        // 生成getter方法
        for (ColumnInfo col : columns) {
            String getterName = "get" + capitalize(col.getColumnName());
            code.append("    public ").append(col.getJavaType()).append(" ").append(getterName)
                    .append("() { return this.").append(col.getColumnName()).append("; }\n");
        }
        // 新增通过ID获取枚举的方法
        code.append("\n    public static ").append(className)
                .append(" fromId(").append(idJavaType).append(" id) {\n")
                .append("        return ID_MAP.get(id);\n")
                .append("    }\n");

        code.append("}\n");

        // 写入文件
        Files.write(Paths.get(className + ".java"), code.toString().getBytes());
    }

    private static String resolveJavaType(Integer jdbcType) {
        switch (jdbcType) {
            case Types.INTEGER:
                return "int";
            case Types.BIGINT:
                return "Long";
            case Types.VARCHAR:
            case Types.CHAR:
                return "String";
            case Types.BOOLEAN:
                return "Boolean";
            case Types.DOUBLE:
                return "double";
            case Types.DATE:
                return "java.sql.Date";
            case Types.TIMESTAMP:
                return "java.sql.Timestamp";
            default:
                return "Object";
        }
    }

    private static String toJavaLiteral(Object value, String javaType) {
        if (value == null) return "null";
        switch (javaType) {
            case "int":
                return Integer.toString((Integer) value);
            case "long":
                return Long.toString((Long) value);
            case "boolean":
                return (Boolean) value ? "true" : "false";
            case "double":
                return Double.toString((double) value);
            case "String":
                return "\"" + escapeString(value.toString()) + "\"";
            case "java.sql.Date":
                return "java.sql.Date.valueOf(\"" + value.toString() + "\")";
            case "java.sql.Timestamp":
                return "java.sql.Timestamp.valueOf(\"" + value.toString() + "\")";
            default:
                return "\"" + escapeString(value.toString()) + "\"";
        }
    }

    private static String escapeString(String s) {
        return s.replace("\"", "\\\"").replace("\n", "\\n");
    }

    private static String sanitizeEnumName(String name) {
        String trimmed = name.trim();
        // 将连续的空格或连字符替换为单个下划线
        String cleaned = trimmed.
                replaceAll("[\\s-]+", "_")
                // 移除非字母数字字符（允许下划线）
                .replaceAll("[^A-Za-z0-9_]", "_")
                .toUpperCase();

        // 合并连续的下划线（可选步骤）
        cleaned = cleaned.replaceAll("_+", "_");

        // 处理数字开头的情况
        if (cleaned.matches("^\\d.*")) cleaned = "_" + cleaned;

        if (!cleaned.isEmpty() && "_".equals(String.valueOf(cleaned.charAt(cleaned.length() - 1)))) {
                cleaned = cleaned.substring(0, cleaned.length() - 1);
        }

        // 处理空字符串
        return cleaned.isEmpty() ? "_EMPTY" : cleaned;
    }

    private static String convertToPascalCase(String tableName) {
        StringBuilder sb = new StringBuilder();
        for (String part : tableName.split("_")) {
            if (!part.isEmpty()) {
                sb.append(Character.toUpperCase(part.charAt(0)))
                        .append(part.substring(1));
            }
        }
        return sb.toString();
    }

    private static String capitalize(String s) {
        if (s == null || s.isEmpty()) return s;
        return Character.toUpperCase(s.charAt(0)) + s.substring(1);
    }
}